package basic;

import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import com.google.common.base.Function;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
/**
 * Ordering是一个排序的帮助类，为什么要使用它？
 * 因为有时候要比较的类没有实现Comparable接口，再不能修改源码又要实现比较时，可以使用Ordering来帮助排序。
 * 实现了Comparable接口的类，还是可以使用老方法进行排序
 * @author tiangh
 * 2013-5-26 上午11:08:16
 */
public class OrderingDemo {
	
	public static Collator comparator = Collator.getInstance(Locale.CHINA);
	public static ArrayList<Foo> data = Lists.newArrayList(
			new Foo("aaa", 1,"打赏点啊"),
			new Foo("bfdf", 9,"asa"),
			new Foo("木插画", -1,"哈哈"),
			new Foo("你好",13,"打赏点啊"),
			null,
			new Foo("你好",7,"打赏点啊")
			);
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		explicitDemo();
	}
	
	public static void OrderingConstructor() {
		
		//当Foo实现了Comparable接口时，可以直接排序
//		Collections.sort(data);
//		System.out.println(data);
		
		//假若Foo没有实现Comparable接口，又不允许修改源代码，可以使用Ordering来帮助排序
		//它比Comparator使用起来更加方便，可以组合成各种形式
		//执行顺序为，先把null值放到最前，然后对Foo的A字段使用comparator执行排序
		//然后使用第二个排序器，在之前的结果上，对Foo的C字段使用comparator执行排序
		//然后使用第三个排序器，在之前的结果上，对Foo的B字段使用natural执行排序
		Ordering<Foo> ordering = 
				Ordering.from(comparator).onResultOf(AFunction.GET_A).nullsFirst()
				.compound(Ordering.from(comparator).onResultOf(AFunction.GET_C))
				.compound(Ordering.natural().onResultOf(BFunction.GET_B));
		List<Foo> sortedCopy = ordering.sortedCopy(data);
		System.out.println(sortedCopy);
		
		//除了用静态方法构造以外，也可以自己实现一个Ordering
		Ordering<Foo> ordering2=new Ordering<OrderingDemo.Foo>() {
			@Override
			public int compare(Foo left, Foo right) {
				if (right==null) {
					if (left==null) {
						return 0;
					}else {
						return 1;
					}
				}
				return ComparisonChain.start().compare(left.A,right.A,comparator).compare(left.C,right.C,comparator).compare(left.B, right.B).result();
			}
		};
		sortedCopy=ordering2.sortedCopy(data);
		System.out.println(sortedCopy);
	}
	/**
	 * greatestOf使用当前排序器排序list后，返回一个从大到小，容量为k的list
	 * 如果k大于list的size，那么返回倒序的list
	 * 返回的list是不可变的
	 */
	public static void greatestOfDemo () {
		Ordering<Foo> ordering = Ordering.from(comparator).onResultOf(AFunction.GET_A).nullsFirst();
		List<Foo> greatestOf = ordering.greatestOf(data, 4);
		System.out.println(greatestOf);
		
		greatestOf = ordering.greatestOf(data, 9);
		System.out.println(greatestOf);
		
	}
	
	public enum AFunction implements Function<Foo, String> {
		GET_A {
			@Override
			public String apply(Foo input) {
				return input.A;
			}
		},
		GET_C {
			@Override
			public String apply(Foo input) {
				return input.C;
			}
		};
	}
	public enum BFunction implements Function<Foo, Integer> {
		GET_B {
			@Override
			public Integer apply(Foo input) {
				return input.B;
			}
		};
	}
	
	/**
	 * 根据一个给定的顺序排序
	 */
	public static void explicitDemo() {
		//经常出现的情景，一个是对象id的集合，一个是对象的集合。
		//期望对象按照它的id在id集合里的顺序，让对象集合进行排序
		 ArrayList<Integer> ids = Lists.newArrayList(1,3,19,5);
		 ArrayList<Foo> list = Lists.newArrayList(
				 new Foo("张三", 1, "湖南"),
				 new Foo("李四", 19, "湖北"),
				 new Foo("王五", 5, "安徽"),
				 new Foo("赵六", 3, "河南"),
				 new Foo("马七", 3, "黑龙江"),
				 new Foo("冯八", 1, "吉林"),
				 new Foo("郭九", 19, "海南"));
		 
		 Ordering<Foo> ordering = Ordering.explicit(ids).onResultOf(BFunction.GET_B);
		 List<Foo> sortedCopy = ordering.sortedCopy(list);
		 System.out.println(sortedCopy);
	}
	
	public static class Foo implements Comparable<Foo>{
		public String A;
		public int B;
		public String C;
		
		public Foo() {
		}

		public Foo(String a, int b, String c) {
			A = a;
			B = b;
			C = c;
		}



		@Override
		public String toString() {
			return "(A=" + A + ", B=" + B + ", C=" + C + ")";
		}

		@Override
		public int compareTo(Foo o) {
//			//第一种排序，传统方式
//			if (o==null) {
//				return 1;
//			}
//			int compare = comparator.compare(A, o.A);
//			
//			if (compare==0) {
//				compare=comparator.compare(C, o.C);
//			}
//			
//			if (compare==0) {
//				compare=Ints.compare(B, o.B);
//			}
//			return compare;
			
			//第二种方式实现排序，更加简单
			if (o==null) {
				return 1;
			}
			return ComparisonChain.start().compare(A,o.A,comparator).compare(C,o.C,comparator).compare(B, o.B).result();
		}
	}

}
